/* Copyright 2024 Coremail
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
export class CmTimeManager {
  static TimeIntervalInMs_Hour: number = 3600 * 1000;
  static TimeIntervalInMs_Day: number = 3600 * 1000 * 24;
  static TimeIntervalInMs_Week: number = 3600 * 1000 * 24 * 7;
  static TimeIntervalInMs_Week2: number = 3600 * 1000 * 24 * 7 * 2;

  //utc的今天0点时间
  static todayZeroTimestamp:number|null;
  /**
   * MM-DD
   *
   * M代表月,2个M代表01格式,加前导0
   * D代表天数.
   * @param timestamp
   * @returns
   */
  static relativeTimeStringFromNow(timestamp: number, format: string): string {
    let date = new Date(timestamp);
    let Y = date.getFullYear();

    //有两个M才填充满
    let hasTwoM = format.search("MM") != -1;
    let _M: number = date.getMonth() + 1;
    let M: string = _M.toString();
    if (hasTwoM) {
      M = _M < 10 ? '0' + _M : M;
    }

    let _D = date.getDate() + 1, D: string = _D.toString();
    let hasTowD = format.search("DD") != -1;
    if (hasTowD) {
      D = _D < 10 ? '0' + _D : D;
    }
    let h = date.getHours();
    let m = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes();
    let s = date.getSeconds();

    // WARN: 格式的大小写其实有区别，但暂时先做一样看待
    let dateStr = format.replace(new RegExp("[y|Y]+"), `${Y}`)
    dateStr = dateStr.replace(new RegExp("[m|M]+"), `${M}`)
    dateStr = dateStr.replace(new RegExp("[d|D]+"), `${D}`)
    dateStr = dateStr.replace(new RegExp("[h|H]+"), `${h}`)
    dateStr = dateStr.replace(new RegExp("[m|M]+"), `${m}`)
    dateStr = dateStr.replace(new RegExp("[s|S]+"), `${s}`)
    return dateStr
  }

  static dateStringWithFormatHHmm(date:Date,seperator:string= ""): string {
    let h = date.getHours();
    let hStr = h < 10 ? '0' + h : h ;
    let m = date.getMinutes();
    let mStr = m < 10 ? '0' + m : m;
    return `${hStr}${seperator}${mStr}`;
  }

  static dateStringWithFormatYYYYMMDD(date:Date,seperator:string = "-"): string {
    let Y = date.getFullYear();
    let M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1);
    let D = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
    return `${Y}${seperator}${M}${seperator}${D}`
  }

  /**
   * 返回今天的日期字符串 YYYY-MM-DD
   */
  static dateStringForNow(): string {
    let date = new Date();
    let Y = date.getFullYear();
    let M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1);
    let D = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
    return `${Y}-${M}-${D}`
  }

  /**
   * 返回当前月份 [1,12]
   * @returns
   */
  static getMonthForNow(): number {
    return new Date().getMonth() + 1;
  }

  static getMonthForTime(ts: number): number {
    return new Date(ts).getMonth() + 1;
  }

  static getYearForTime(ts: number): number {
    return new Date(ts).getFullYear()
  }


  /**
   * 返回今天的日期字符串 hh-mm-ss
   */
  static stdDateTimeStringForNow(): string {
    let date = new Date();
    return CmTimeManager.stdDateTimeStringForDate(date);
  }

  static stdDateTimeStringForDate(date: Date): string {
    let Y = date.getFullYear();
    let M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1);
    let D = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
    let h = date.getHours() < 10 ? '0' + date.getHours() : date.getHours();
    let m = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes();
    let s = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds();
    let todayStr = this.dateStringForNow()
    let timeStr = `${Y}-${M}-${D} ${h}:${m}:${s}`
    if (timeStr.search(todayStr) != -1) {
      return `${h}:${m}:${s}`
    } else {
      return timeStr
    }
  }

  static dayOfWeekForNow(): number {
    let date = new Date();
    return CmTimeManager.dayOfWeekForDate(date);
  }

  /**
   * case 1:
   return "星期一";
   case 2:
   return "星期二";
   case 3:
   return "星期三";
   case 4:
   return "星期四";
   case 5:
   return "星期五";
   case 6:
   return "星期六";
   default:
   case 0:
   return "星期日";
   * @param date
   */
  public static dayOfWeekForDate(date: Date): number {
    let d = date.getDay();
    return d;
  }

  /**
   * 现在距离UTC时间的秒数.
   */
  static curerntTimeInterval(): number {
    let date = new Date();
    return date.getTime()
  }


  /**
   * 返回距离今天0点指定间隔(ms)的时间.
   * @param intervalInMs
   * @returns
   */
  public static dateWithIntervalSinceTodayZeroDate(intervalInMs: number | null): Date {
    if (intervalInMs == null) {
      intervalInMs = 0;
    }
    //时间戳,毫秒数,Date没有类方法????
    //$0 h,$1 m,$2 s,$3 ms
    let date = new Date(new Date().setHours(0, 0, 0, 0) + intervalInMs);
    return date;
  }

  public static tsInMsWithIntervalSinceTodayZeroDate(intervalInMs: number | null): number {
    let date = CmTimeManager.dateWithIntervalSinceTodayZeroDate(intervalInMs);
    return date.getTime();
  }


  public static zeroDateForToday(): Date {
    return CmTimeManager.dateWithIntervalSinceTodayZeroDate(0);
  }

  public static zeroDateForYesterday(): Date {
    return CmTimeManager.dateWithIntervalSinceTodayZeroDate(-CmTimeManager.TimeIntervalInMs_Day);
  }

  public static dateWithIntervalSinceDate(date: Date, tsInMs: number): Date {
    let tsInMs_origin = date.getTime() + tsInMs;
    return new Date(tsInMs_origin);
  }

  public static zeroDateForLastMonthFirstDay(date?: Date): Date {
    if (date == null) {
      date = new Date();
    }
    let m = date.getMonth();
    let d = 1;
    let y = date.getFullYear();
    if (m == 0) {
      y -= 1;
      m = 11;
    }
    else {
      m--;
    }
    let date_result = new Date(y, m, d)
    return date_result;
  }

  public static zeroTimeForTodayThisYearFirstDay(): number {
    let y = new Date().getFullYear();
    let date = new Date(y, 0, 0);
    return date.getTime();
  }

  public static zeroDateForThisMonthFirstDay(date?: Date): Date {
    if (date == null) {
      date = new Date();
    }
    let m = date.getMonth();
    let d = 1;
    let y = date.getFullYear();
    let date_result = new Date(y, m, d)
    return date_result;
  }

  //上周一的0点.
  public static zeroDateForLastWeekSunday(): Date {
    let date = CmTimeManager.zeroDateForThisWeekMonday(-CmTimeManager.TimeIntervalInMs_Week);
    return date;
  }

  /**
   * 返回本周一0点
   * 根据今天0点计算

   // case 1: return "星期一";
   // case 2: return "星期二";
   // case 3: return "星期三";
   // case 4: return "星期四";
   // case 5: return "星期五";
   // case 6: return "星期六";
   // default: case 0: return "星期日";
   */
  public static zeroDateForThisWeekMonday(intervalInMs: number = 0): Date {
    let date = new Date();
    let day = CmTimeManager.dayOfWeekForDate(date);
    let dayInterval = 0;
    switch (day) {
      case 0:
        dayInterval = 6;
      default:
        dayInterval = day - 1;
    }
    return CmTimeManager.dateWithIntervalSinceTodayZeroDate(-CmTimeManager.TimeIntervalInMs_Day * dayInterval + intervalInMs);
  }

  /**
   * 指定时间戳 离今天零点的时间.
   * @param t
   * @returns
   * 正数说明指定时间大于今天0点.
   * 负数说明指定时间小于今天0点.
   */
  static timeIntervalInMsToTodayZeroTime(timeIntervalInMs: number): number {
    let ts_today = CmTimeManager.zeroDateForToday().getTime();
    let interval = timeIntervalInMs - ts_today;
    return interval;
  }

  /**
   * 邮件中各种时间字符串
   * 转化为timestamp
   */
  static timeStringToTimeTs(rd: string): number {
    if (rd && rd.length > 0) {
      let ms = 0;
      if (rd.search("CST") != -1) {
        //中美洲标准时间
        //CST时间解析不出来.
        let rd2 = rd.replace("CST", "UTC");
        let date = new Date(Date.parse(rd2));
        let arr = rd2.split(" ");
        ms = date.getTime()
        // 6个: 22 Nov 2023 00:28:53 +0800 (UTC)
        // 7个: wed 22 Nov 2023 00:28:53 +0800 (UTC)
        // 获取时区字符串 类似:+0800
        if (arr.length == 7 || arr.length == 6) {
          let timeZoneOffsetStr = arr[arr.length - 2];
          let timeZoneOffset = Number.parseInt(timeZoneOffsetStr);
          let offsetMs = timeZoneOffset / 100 * 3600 * 1000
          let fixedMs = ms - offsetMs
          return fixedMs;
        }
      }
      else if (rd.search("CDT") != -1) {
        //
        let rd2 = rd.replace("CDT", "UTC");
        let date = new Date(Date.parse(rd2));
        let arr = rd2.split(" ");
        ms = date.getTime()
        if (arr.length == 7 || arr.length == 6) {
          let timeZoneOffsetStr = arr[arr.length - 2];
          let timeZoneOffset = Number.parseInt(timeZoneOffsetStr);
          let offsetMs = timeZoneOffset / 100 * 3600 * 1000
          let fixedMs = ms - offsetMs
          return fixedMs;
        }
      }
      else {
        //utc时间直接解析
        let date = new Date(Date.parse(rd));
        ms = date.getTime()
        if (ms == null || ms == 0) {
        }
        return ms;
      }
      //毫秒数
      // hilog.debug(0x0,"MAIL",`msgNo: ${msgNo},date: ${rd} -> ${entity.receivedDate}`)

    }
    else {
      return 0;
    }
  }

  /**
   * 获取今天0点的utc时间
   * TODO:当时间过了今天,需要更新一次.
   * @returns
   */
  static getTodayZeroTs(): number {
    if(!CmTimeManager.todayZeroTimestamp) {
      CmTimeManager.todayZeroTimestamp = CmTimeManager.zeroDateForToday().getTime();
    }
    return CmTimeManager.todayZeroTimestamp;
  }

  /**
   * 将时间戳显示为App层面需要展示的时间
   */
  static getDisplayTimeStringForTs(timestamp:number):string {
    let date = new Date(timestamp);
    if(timestamp > CmTimeManager.getTodayZeroTs()) {
      //今天的.
      return CmTimeManager.dateStringWithFormatHHmm(date);
    }
    else {
      //昨天以及之前的.
      return CmTimeManager.dateStringWithFormatYYYYMMDD(date);
    }
  }
  static getDisplayTimeStringForDate(date:Date):string {
    let timestamp = date.getTime();
    if(timestamp > CmTimeManager.getTodayZeroTs()) {
      //今天的.
      return CmTimeManager.dateStringWithFormatHHmm(date,":");
    }
    else {
      //昨天以及之前的.
      return CmTimeManager.dateStringWithFormatYYYYMMDD(date,"/");
    }
  }
}